package com.zhengbing.tj.utils;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 文件上传下载工具类
 * 提供本地文件系统的文件上传、下载、删除等功能
 *
 * @author zhengbing
 * @date 2025-07-30
 */
@Component
public class FileUploadDownloadUtil {

    @Value("${file.upload.path:./uploads}")
    private String uploadPath;

    @Value("${file.max.size:10485760}")
    private long maxFileSize;

    @Autowired
    @Qualifier("fileExecutorService")
    private ExecutorService fileExecutorService;

    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

    /**
     * 上传文件到本地服务器
     *
     * 异步上传文件到本地服务器，使用线程池处理文件写入操作
     *
     * @param file 待上传的MultipartFile对象
     * @return CompletableFuture<String> 包含生成的唯一文件名（格式：日期目录/UUID.扩展名）
     * @throws CompletionException 包装IOException，文件大小超过限制或保存失败时抛出
     */
    public CompletableFuture<String> uploadFile(MultipartFile file) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                // 验证文件大小
                if (file.getSize() > maxFileSize) {
                    throw new IOException("文件大小超过限制: " + maxFileSize / 1024 / 1024 + "MB");
                }

                // 创建日期目录
                String dateDir = dateFormat.format(new Date());
                Path uploadDir = Paths.get(uploadPath, dateDir);
                if (!Files.exists(uploadDir)) {
                    Files.createDirectories(uploadDir);
                }

                // 生成唯一文件名
                String originalFilename = file.getOriginalFilename();
                String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                String fileName = UUID.randomUUID().toString() + "." + fileExtension;

                // 保存文件
                Path filePath = uploadDir.resolve(fileName);
                file.transferTo(filePath);

                // 返回相对路径（日期目录+文件名）
                return dateDir + File.separator + fileName;
            } catch (IOException e) {
                throw new CompletionException(e);
            }
        }, fileExecutorService);
    }

    /**
     * 根据文件名下载文件
     *
     * 异步下载文件，使用线程池处理文件读取操作
     *
     * @param fileName 文件名（包含日期目录，与上传时返回的相对路径一致）
     * @return CompletableFuture<Resource> 包含文件资源的异步结果
     * @throws CompletionException 包装MalformedURLException，文件不存在或路径错误时抛出
     */
    public CompletableFuture<Resource> downloadFile(String fileName) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                Path filePath = Paths.get(uploadPath).resolve(fileName);
                Resource resource = new UrlResource(filePath.toUri());
                if (resource.exists() && resource.isReadable()) {
                    return resource;
                } else {
                    throw new MalformedURLException("文件不存在或无法读取: " + fileName);
                }
            } catch (MalformedURLException e) {
                throw new CompletionException(e);
            }
        }, fileExecutorService);
    }

    /**
     * 删除文件
     *
     * 异步删除文件，使用线程池处理文件删除操作
     *
     * @param fileName 文件名（包含日期目录，与上传时返回的相对路径一致）
     * @return CompletableFuture<Boolean> 异步结果：true表示删除成功，false表示文件不存在或删除失败
     */
    public CompletableFuture<Boolean> deleteFile(String fileName) {
        Path filePath = Paths.get(uploadPath).resolve(fileName);
        return CompletableFuture.supplyAsync(() -> {
            try {
                return Files.deleteIfExists(filePath);
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }, fileExecutorService);
    }

    /**
     * 获取文件存储根路径
     *
     * @return 上传根路径
     */
    public String getUploadPath() {
        return uploadPath;
    }

    /**
     * 设置文件存储根路径
     *
     * @param uploadPath 上传根路径
     */
    public void setUploadPath(String uploadPath) {
        this.uploadPath = uploadPath;
    }

    /**
     * 获取最大文件大小限制
     *
     * @return 最大文件大小（字节）
     */
    public long getMaxFileSize() {
        return maxFileSize;
    }

    /**
     * 设置最大文件大小限制
     *
     * @param maxFileSize 最大文件大小（字节）
     */
    public void setMaxFileSize(long maxFileSize) {
        this.maxFileSize = maxFileSize;
    }
}